每家店(Store)除了可以賣很多種商品之外,每種商品也可以在很多家商店販售。
多對多的關連會需要一個**第三方的資料表(Table)**來存放這兩邊 Model 的資訊(關聯表的主鍵)。
第一步建立一個專門存放 Store 跟 Product 這兩邊資訊的 Model:WareHouserails g model WareHouse store:references product:references
這裡的 store:references 寫法也可以換成store_id:integer 寫法,
但 references 的寫法會多做幾件事:
第二步建立關聯
Store Model
class Store < ApplicationRecord
belongs_to :user
# 先告訴Model我们在ware_houses有很多筆資料
has_many :ware_houses
# 這些資料是要拿来判斷這間商店販賣多少商品
has_many :products, through: :ware_houses
end
Product Model
class Product < ApplicationRecord
# 先告訴Model我们在ware_houses有很多筆資料
has_many :ware_houses
# 這些資料是要拿来判斷這個商品在哪些商店販賣
has_many :stores, through: :ware_houses
end
WareHouse Model
class WareHouse < ApplicationRecord
#WareHouse要管理好商品和商店,
#所以WareHouse會belongs_to商品和商店。
#透過foreign_key: true 確保資料表之間的資料完整性
belongs_to :store
belongs_to :product
end
另一種寫法HABTM(has_and_belongs_to_many)
創建了 has_and_belongs_to_many 的關係,你就需要創建一個第三方的資料表(Table)存放雙方的資訊,只是這個資料表因為不重要也不會存取它,所以可以不需要創立Model 對應。
這個第三方資料表的名字是有規定的,如果你沒有在創建關係時使用 join_table 參數,預設是「兩個資料表依照英文字母先後順序排序,中間以底線分格」,所以以我們這個例子來說,這個資料表的名字就是「products_stores」,因為字母 P 在字母 S 的前面。
(在使用 HABTM 的時候,是可以加註 join_table: "ware_houses" 的方式來指定這個資料表的名稱)
第一步建立關聯
Store Model
class Store < ActiveRecord::Base
has_and_belongs_to_many :products
end
Product Model
class Product < ActiveRecord::Base
has_and_belongs_to_many :stores
end
第二步新增一個 Migration 來建立資料表rails g migration create_join_table_for_store_and_product
class CreateJoinTableForStoreAndProduct < ActiveRecord::Migration[5.0]
def change
create_table :products_stores, id: false do |t|
t.belongs_to :store, index: true
t.belongs_to :product, index: true
end
end
end
rails db:migration
id 這是 Rails 自動幫每個資料表加的流水編號欄位,這個欄位稱為資料表的主鍵(Primary Key)。如果你不想要這個主鍵,可以在 Migration 的時候加上 id: false 參數。
該選擇 has_many ... through 還是 has_and_belongs_to_many 的寫法?
參考資料:
為自己學Ruby on Rails
Rails Guide: Active Record 關聯